package org.dynobjects.core;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.dynobjects.core.xml.Attribute;
import org.dynobjects.core.xml.Model;

/**
 * Recupera il modello xml dal ResourceLoader e genera il codice java del bean.
 * Questo viene memorizzata dentro la map e puo' essere recuperato chiamando il
 * metodo getSourcesMap().
 * 
 * @author epelli
 * 
 */
public class BeanCreator {

	private ResourceLoader resourceLoader = new DefaultResourceLoader();

	private List resources;

	private String castorMapping = "classpath:dynobjects.cm.xml";

	private static Map sourcesContainer = new HashMap();

	public BeanCreator() {
	}

	public void createSourceCode() {
		try {
			// prelevo le risorse con i modelli dei bean da caricare
			ResourceContainer in = resourceLoader.loadResources(resources);

			InputStream[] modelsStream = in.getResources();
			ResourceResolver resolver = new ResourceResolver();
			InputStream castorMappingStream = resolver.resolve(castorMapping);

			for (int i = 0; i < modelsStream.length; i++) {

				XmlHandler xmlHandler = new XmlHandler(modelsStream[i],
						castorMappingStream);
				// carico i modelli
				Collection models = (Collection) xmlHandler
						.unmarshall(ArrayList.class);

				for (Iterator iter = models.iterator(); iter.hasNext();) {
					Model model = (Model) iter.next();
					// creo i beans
					create(model);

				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void create(Model model) {
		String _extends = model.getExtends() == null ? "" : " extends "
				+ model.getExtends();
		_extends = _extends == null ? "" : _extends;
		String _package = model.getClassName().substring(0,
				model.getClassName().lastIndexOf("."));
		String _className = model.getClassName().substring(
				model.getClassName().lastIndexOf(".") + 1);
		String OPEN_GRAFFA = "{";
		String CLOSE_GRAFFA = "}";
		String OPEN_TONDA = "(";
		String CLOSE_TONDA = ")";
		String _implements = "implements java.io.Serializable";
		List attributesList = new ArrayList();
		List setMethodList = new ArrayList();
		List getMethodList = new ArrayList();
		Collection attributes = model.getAttribute();
		for (Iterator iterator = attributes.iterator(); iterator.hasNext();) {
			Attribute att = (Attribute) iterator.next();
			String name = att.getName();
			String type = att.getType();
			StringBuffer sbFields = new StringBuffer();
			sbFields.append("private ").append(type).append(" ").append(name)
					.append(" = null;\n");
			attributesList.add(sbFields.toString());
			StringBuffer sbSetMethod = new StringBuffer();
			sbSetMethod.append("public void set").append(
					StringUtils.capitalize(name)).append(" ");
			sbSetMethod.append(OPEN_TONDA).append(type).append(" ")
					.append(name).append(CLOSE_TONDA).append(OPEN_GRAFFA);
			sbSetMethod.append("\t").append("this.").append(name).append("=")
					.append(name).append(";\n");
			sbSetMethod.append(CLOSE_GRAFFA);
			setMethodList.add(sbSetMethod.toString());

			StringBuffer sbGetMethod = new StringBuffer();
			sbGetMethod.append("public ").append(type).append(" get").append(
					StringUtils.capitalize(name)).append(" ");
			sbGetMethod.append(OPEN_TONDA).append(" ").append(CLOSE_TONDA)
					.append(OPEN_GRAFFA);
			sbGetMethod.append("\t").append("return ").append(name).append(
					";\n");
			sbGetMethod.append(CLOSE_GRAFFA);
			getMethodList.add(sbGetMethod.toString());

		}

		StringBuffer sbClass = new StringBuffer();
		sbClass.append("package ").append(_package).append(";\n");
		sbClass.append("public class ").append(_className).append("  ").append(
				_extends).append(" ").append(_implements).append(OPEN_GRAFFA);

		for (int i = 0; i < attributesList.size(); i++) {
			String attribute = (String) attributesList.get(i);
			String set = (String) setMethodList.get(i);
			String get = (String) getMethodList.get(i);
			sbClass.append(attribute);
			sbClass.append(set);
			sbClass.append(get);

		}

		sbClass.append(CLOSE_GRAFFA);

		System.out.println(sbClass.toString());
		String resourceName = StringUtils.replaceChars(_package, ".", "/")
				+ "/" + _className + ".java";

		// memorizzo i sorgenti creati. Diventa una sorta di repository virtuale
		// dei sorgenti
		sourcesContainer.put(resourceName, sbClass.toString());

	}

	public Map getSourcesContainer() {
		return sourcesContainer;
	}

	public ResourceLoader getResourceLoader() {
		return resourceLoader;
	}

	public void setResourceLoader(ResourceLoader resourceLoader) {
		this.resourceLoader = resourceLoader;
		try {
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public List getResources() {
		return resources;
	}

	public void setResources(List resources) {
		this.resources = resources;
	}

	public String getCastorMapping() {
		return castorMapping;
	}

	public void setCastorMapping(String castorMapping) {
		this.castorMapping = castorMapping;
	}

}
